/*
 * Copyright (c) 2008, Roman Bosak
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 *  - Redistributions of source code must retain the above copyright notice,
 *    this list of conditions and the following disclaimer.
 *  - Redistributions in binary form must reproduce the above copyright notice,
 *    this list of conditions and the following disclaimer in the documentation
 *    and/or other materials provided with the distribution.
 *  - Neither the name of the DailyDevelopment nor the names of its contributors
 *    may be used to endorse or promote products derived from this software
 *    without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
 * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
 * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
 * THE POSSIBILITY OF SUCH DAMAGE.
 */
package com.atlassian.jira.web.action.portal;

import java.util.Collection;

import com.atlassian.jira.util.EmailFormatter;
import com.atlassian.jira.web.action.JiraWebActionSupport;
import com.atlassian.jira.web.bean.FilterUtils;
import com.dailydev.jira.portal.config.IPortalPageSharingConfiguration;
import com.dailydev.jira.portal.config.ISharedPortalPage;
import com.dailydev.jira.portal.config.SharedPortalPage;
import com.opensymphony.util.TextUtils;

/**
 * Webwork action implementing functionality of portal page sharing. Action can
 * configure portal page of currently logged user to be shared to one of his
 * group, change target group and also unshare of the portal page.
 * 
 * @author Roman Bosak, roman.bosak@gmail.com
 */
public class SharePortalPage extends JiraWebActionSupport {

    /**
     * Constant for sharing option - shared to group.
     */
    public static final String OPTION_GROUPSHARE = "groupshare";

    /**
     * Constant for sharing option - shared to all.
     */
    public static final String OPTION_PUBLIC = "public";

    /**
     * Constant for sharing option - not shared.
     */
    public static final String OPTION_NOTSHARED = "notshared";

    /**
     * Key for error message 'You must select a sharing option'.
     */
    protected static final String MSG_SELECT_SHARING = "shareportalpage.select.sharing";

    /**
     * Key for error message 'A portal page has not been specified - please pick
     * one'.
     */
    protected static final String MSG_PICK_PAGE = "shareportalpage.pick.page";

    /**
     * Key for error message 'Please select a group to share this portal page
     * with'.
     */
    protected static final String MSG_SELECT_GROUP = "shareportalpage.share.select.group";

    /**
     * Serial version UID.
     */
    private static final long serialVersionUID = -3020616584954363736L;

    /**
     * Reference to {@link EmailFormatter} to format emails for the UI.
     */
    private final transient EmailFormatter emailFormatter;

    /**
     * ID of the selected page to be shared.
     */
    private Long pageId;

    /**
     * List of options for sharing [notshared - will not be shared (private
     * dashboard) - public - will be shared to everybody - groupshare - will be
     * shared to specific group].
     */
    private final String[] options = {OPTION_NOTSHARED, OPTION_PUBLIC,
            OPTION_GROUPSHARE};

    /**
     * Sharing option selected by user.
     */
    private String option;

    /**
     * {@link Collection} of group names of current user.
     */
    private Collection groups;

    /**
     * Name of selected group when option 'groupshare' is selected.
     */
    private String group;

    /**
     * Reference to {@link IPortalPageSharingConfiguration} to provide dashboard
     * sharing configuration management.
     */
    private final transient IPortalPageSharingConfiguration configuration;

    /**
     * Constructor for {@link SharePortalPage} with defined
     * <code>configuration</code> and <code>emailFormatter</code>.
     * 
     * @param configuration
     *            reference to {@link IPortalPageSharingConfiguration} instance
     *            provided by Jira
     * @param emailFormatter
     *            reference to {@link EmailFormatter} instance provided by Jira
     */
    public SharePortalPage(final IPortalPageSharingConfiguration configuration,
            final EmailFormatter emailFormatter) {
        this.configuration = configuration;
        this.emailFormatter = emailFormatter;
    }

    /**
     * Extends super implementation of this method and sets {@link #option} and
     * {@link #group} parameters of this action to reflect current sharing
     * configuration for page specified by {@link #pageId}.
     * 
     * @return Returns name of view for the action to be forwarded to. Returns
     *         same value as {@link webwork.action.ActionSupport#doDefault()}
     * @throws Exception
     *             throws for same reason as
     *             {@link webwork.action.ActionSupport#doDefault()}.
     * 
     * @see webwork.action.ActionSupport#doDefault()
     */
    @Override
    public String doDefault() throws Exception {
        if (log.isDebugEnabled()) {
            log.debug("doDefault: pageId> " + pageId);
        }

        ISharedPortalPage sharedDashboard = configuration
                .getSharedPortalPage(pageId);

        if (sharedDashboard == null) {
            this.setOption(OPTION_NOTSHARED);
        } else if (sharedDashboard.getGroupName() == null
                || sharedDashboard.getGroupName().length() == 0) {
            this.setOption(OPTION_PUBLIC);
        } else {
            this.setOption(OPTION_GROUPSHARE);
            this.setGroup(sharedDashboard.getGroupName());
        }

        return super.doDefault();
    }

    /**
     * Manipulates with portal page sharing configurations within referred
     * {@link IPortalPageSharingConfiguration} instance to reflect
     * configurations made by user.
     * 
     * @return Returns redirect to <code>SetupPortal.jspa</code> page.
     * @throws Exception
     *             throws for same reason as
     *             {@link JiraWebActionSupport#doDefault()}.
     * 
     * @see webwork.action.ActionSupport#doExecute()
     */
    @Override
    protected String doExecute() throws Exception {
        if (log.isDebugEnabled()) {
            log.debug("doExecute: pageId> " + pageId + "; option> "
                    + getOption() + "; group> " + getGroup());
        }

        if (OPTION_NOTSHARED.equals(getOption())) {
            configuration.removeSharedPortalPage(getPageId());
        } else if (OPTION_PUBLIC.equals(getOption())) {
            SharedPortalPage newSharing = new SharedPortalPage(getPageId(),
                    getRemoteUser().getName(), null);
            configuration.addSharedPortalPage(newSharing);
        } else if (OPTION_GROUPSHARE.equals(getOption())) {
            SharedPortalPage newSharing = new SharedPortalPage(getPageId(),
                    getRemoteUser().getName(), getGroup());
            configuration.addSharedPortalPage(newSharing);
        }

        return getRedirect("SetupPortal.jspa");
    }

    /**
     * Extends super implementation of this method validating that page for
     * sharing is selected, proper sharing option is selected and that also
     * proper group is selected in case of sharing to group.
     * 
     * @see webwork.action.ActionSupport#doValidation()
     */
    @Override
    protected void doValidation() {
        super.doValidation();

        if (getPageId() == null) {
            addErrorMessage(getText(MSG_PICK_PAGE));
        } else {
            if (OPTION_GROUPSHARE.equals(getOption())) {
                if (!TextUtils.stringSet(getGroup())
                        || !getGroups().contains(group)) {
                    addError("group", getText(MSG_SELECT_GROUP));
                }
            } else if (!OPTION_NOTSHARED.equals(getOption())
                    && !OPTION_PUBLIC.equals(getOption())) {
                addErrorMessage(getText(MSG_SELECT_SHARING));
            }
        }
    }

    /**
     * Returns string representation of users email. Uses {@link EmailFormatter}
     * to format it.
     * 
     * @param email
     *            email to be reformatted
     * @return reformatted email
     */
    public String getDisplayEmail(final String email) {
        return emailFormatter.formatEmailAsLink(email, getRemoteUser());
    }

    /**
     * Returns ID of portal page which sharing parameters will be changed by
     * this action execution.
     * 
     * @return ID of portal page which sharing parameters will be changed by
     *         this action execution
     */
    public Long getPageId() {
        return pageId;
    }

    /**
     * Sets ID of portal page which sharing parameters will be changed by this
     * action execution.
     * 
     * @param pageId
     *            ID of portal page which sharing parameters will be changed by
     *            this action execution
     */
    public void setPageId(final Long pageId) {
        this.pageId = pageId;
    }

    /**
     * Returns array of options for sharing.
     * 
     * @return array of options for sharing
     * @see #options
     */
    public String[] getOptions() {
        return options.clone();
    }

    /**
     * Returns {@link Collection} of group names of current user.
     * 
     * @return {@link Collection} of group names of current user
     */
    public Collection<String> getGroups() {
        if (groups == null) {
            groups = FilterUtils.getGroups(getRemoteUser());
        }
        return groups;
    }

    /**
     * Returns sharing option selected by user.
     * 
     * @return sharing option selected by user
     */
    public String getOption() {
        return option;
    }

    /**
     * Sets sharing option selected by user.
     * 
     * @param option
     *            sharing option selected by user
     */
    public void setOption(final String option) {
        this.option = option;
    }

    /**
     * Returns name of group selected by user to which portal page will be
     * shared.
     * 
     * @return name of group selected by user to which portal page will be
     *         shared
     */
    public String getGroup() {
        return group;
    }

    /**
     * Sets name of group selected by user to which portal page will be shared.
     * 
     * @param group
     *            name of group selected by user to which portal page will be
     *            shared
     */
    public void setGroup(final String group) {
        this.group = group;
    }
}
